package com.ytjj.quartz.service;

import com.ytjj.common.constants.QueueConstants;
import com.ytjj.common.dto.mqdto.OrderRecordDto;
import com.ytjj.common.service.RedisService;
import com.ytjj.qmyx.mall.mapper.*;
import com.ytjj.qmyx.mall.model.*;
import com.ytjj.qmyx.users.client.AdminClient;
import com.ytjj.qmyx.users.mapper.UsersInfoMapper;
import com.ytjj.qmyx.users.mapper.UsersMapper;
import com.ytjj.qmyx.users.model.Users;
import com.ytjj.qmyx.users.model.UsersInfo;
import com.ytjj.qmyx.users.model.UsersInfoExample;
import com.ytjj.quartz.constants.IsPayConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

@Service
@Slf4j
@RefreshScope
public class YxGroupBuyInfoServiceImpl {
    @Resource
    private GroupBuyInfoMapper groupBuyInfoMapper;
    @Resource
    private ProductGroupBuyInfoMapper productGroupBuyInfoMapper;
    @Resource
    private GroupBuyUserRelMapper groupBuyUserRelMapper;
    @Resource
    private UsersInfoMapper usersInfoMapper;
    @Autowired
    private OrdersService ordersService;
    @Resource
    private OrdersInfoMapper ordersInfoMapper;
    @Resource
    private UsersMapper usersMapper;
    @Autowired
    private AdminClient adminClient;
    @Value("${group.virtualTime:1}")
    private Integer virtualTime;
    @Value("${group.orderTimeOut:30}")
    private Integer orderTimeOut;
    @Autowired
    private RedisService redisService;
    @Resource
    private ProductMapper productMapper;
    @Resource
    private YxOrdersSendRecordService yxOrdersSendRecordService;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 1.填充虚拟用户
     * 2.更新团状态
     * @return
     */
    public boolean queryWaitFinalGroupInfoList() {
        //开团信息表
        GroupBuyInfoExample example = new GroupBuyInfoExample();
        example.createCriteria().andFinalResultEqualTo((byte)0);//.andEndTimeGreaterThan(new Date())
        List<GroupBuyInfo> groupInfos = groupBuyInfoMapper.selectByExample(example);
        log.info("====groupInfos.size()==={}", groupInfos.size());

        //查询正常状态并且使用虚拟用户填充的团配置列表
        ProductGroupBuyInfoExample productGroupBuyInfoExample = new ProductGroupBuyInfoExample();
        productGroupBuyInfoExample.createCriteria().andStatusEqualTo((byte)1).andVirtualUseEqualTo((byte)1);
        List<ProductGroupBuyInfo> productGroupBuyInfoList = productGroupBuyInfoMapper.selectByExample(productGroupBuyInfoExample);

        //查询所有虚拟用户
        UsersInfoExample usersInfoExample = new UsersInfoExample();
        usersInfoExample.createCriteria().andIsZombieEqualTo((byte)1);
        List<UsersInfo> userInfoList = usersInfoMapper.selectByExample(usersInfoExample);

        //是否开启团主不参与中奖 1-参与 2-不参与
        Integer groupRoleMainFlag = Integer.parseInt(null == redisService.get("GROUP_MAIN_ROLE_FLAG") ? "2" : redisService.get("GROUP_MAIN_ROLE_FLAG"));

        //如果距离截至时间只剩1个小时以内，然后根据是否需要设置虚拟用户来作相应的处理
        Date addVirtualUserTime = Date.from(LocalDateTime.now().plusHours(virtualTime).atZone(ZoneId.systemDefault()).toInstant());
        groupInfos.stream().forEach(s -> {
            Random random = new Random();
            log.info("====s===={}", s);
            //判断当前团信息是否添加虚拟用户
            List<ProductGroupBuyInfo> matchList = productGroupBuyInfoList.stream().filter(s2 -> s2.getId().equals(s.getGroupId())).collect(Collectors.toList());

            //当前团已参团真实用户信息
            GroupBuyUserRelExample groupBuyUserRelExample = new GroupBuyUserRelExample();
            groupBuyUserRelExample.createCriteria().andGroupIdEqualTo(s.getId()).andStatusEqualTo(1).andVirtualUserEqualTo((byte)0).andOrderNoIsNotNull();
            List<GroupBuyUserRel> buyPersonNum = groupBuyUserRelMapper.selectByExample(groupBuyUserRelExample);

            //团配置信息
            ProductGroupBuyInfo groupInfo = org.apache.commons.collections.CollectionUtils.isEmpty(matchList) ? null : matchList.get(0);
            if (null == groupInfo) {
                ProductGroupBuyInfoExample productGroupBuyInfoExample2 = new ProductGroupBuyInfoExample();
                productGroupBuyInfoExample2.createCriteria().andIdEqualTo(s.getGroupId());
                List<ProductGroupBuyInfo> productGroupBuyInfoList2 = productGroupBuyInfoMapper.selectByExample(productGroupBuyInfoExample2);
                groupInfo = productGroupBuyInfoList2.get(0);
            }
            //如果已满员，则需要修改团为已完成
            log.info("=====groupInfo.getMinPerson() <= buyPersonNum.size()===={}", groupInfo.getMinPerson() <= buyPersonNum.size());
            if (groupInfo.getMinPerson() <= buyPersonNum.size()) {
                s.setFinalResult((byte)1);
                groupBuyInfoMapper.updateByPrimaryKeySelective(s);

                GroupBuyUserRel winFlagObj = null;
                if (groupRoleMainFlag.equals(2)) {
                    List<GroupBuyUserRel> mainGroupRoleExclude = buyPersonNum.stream().filter(userRel -> userRel.getGroupRole() != (byte)1).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(mainGroupRoleExclude) && mainGroupRoleExclude.size() == 1) {
                        winFlagObj = mainGroupRoleExclude.get(0);
                    }else {
                        winFlagObj = mainGroupRoleExclude.get(random.nextInt(mainGroupRoleExclude.size()));
                    }
                }else {
                    winFlagObj = buyPersonNum.get(random.nextInt(buyPersonNum.size()));
                }
                if (null == winFlagObj) {
                    log.info("===没有人中奖，原因：比如3人团，但是设置的时候只需要一人即可成团，但是规则中团主不能中奖，这时候就会出现这种情况==={}", s.getId());
                    return;
                }
                winFlagObj.setWinFlag(1);
                groupBuyUserRelMapper.updateByPrimaryKeySelective(winFlagObj);
                refundOrdersByGroupBuy();
                return;
            }

            if (CollectionUtils.isEmpty(matchList)) {
                log.info("===s.getEndTime().compareTo(new Date()) <= 0==={}", s.getEndTime().compareTo(new Date()) <= 0);
                //表示没有匹配中数据，则不需要添加虚拟用户
                if (s.getEndTime().compareTo(new Date()) <= 0) {
                    //如果成团时间到了，则需要将团设置为相应的状态 1-成团 2-失败
                    s.setFinalResult(groupInfo.getMinPerson() <= buyPersonNum.size() ? (byte)1 : (byte)2);
                    groupBuyInfoMapper.updateByPrimaryKeySelective(s);
                    return;
                }
                //继续成团中...
                return;
            }

            boolean compare = buyPersonNum.size() >= groupInfo.getInventedNum();
            Integer forNum = groupInfo.getMinPerson() - buyPersonNum.size();//forNum(循环次数=团最少成团人数 - 已购买人数)
            Integer maxInventedNum = groupInfo.getInventedNum();//最大机器人数
            if (compare) {
                if (s.getEndTime().compareTo(addVirtualUserTime) <= 0) {
                    for (int i = 0; i < forNum; i++) {
                        log.info("====groupBuyUserRelMapper.insertSelective===={}", s.getEndTime().compareTo(addVirtualUserTime));

                        UsersInfo virtualUser = userInfoList.get(random.nextInt(userInfoList.size()));
                        Users virtualUsers = usersMapper.selectByPrimaryKey(virtualUser.getId());
                        GroupBuyUserRel userRel = new GroupBuyUserRel();
                        userRel.setGroupId(s.getId());
                        userRel.setUserId(virtualUser.getId());
                        userRel.setGroupRole((byte)2);
                        userRel.setVirtualUser((byte)1);
                        userRel.setCreateTime(new Date());
                        userRel.setUserName(null == virtualUsers ? virtualUser.getId().toString() : virtualUsers.getNickname());
                        userRel.setHeadImg(virtualUser.getHeadImg());
                        userRel.setWinFlag(0);
                        userRel.setRedFlag(0);
                        userRel.setStatus(1);
                        groupBuyUserRelMapper.insertSelective(userRel);
                    }
                    successHandle(s, buyPersonNum, random, groupRoleMainFlag);
                    return;
                }
            }
            if (s.getEndTime().compareTo(new Date()) <= 0) {
                if (maxInventedNum <= buyPersonNum.size()) {
                    log.info("====22222222222==========={},{}", maxInventedNum <= buyPersonNum.size(), s.getEndTime().compareTo(new Date()) <= 0);
                    successHandle(s, buyPersonNum, random, groupRoleMainFlag);
                }else {
                    s.setFinalResult((byte)2);
                    groupBuyInfoMapper.updateByPrimaryKeySelective(s);
                }
            }

            //退款 用另一个定时任务来执行
        });
        return true;
    }

    /**
     * 处理拼团成功
     * @param s
     * @param buyPersonNum
     * @param random
     */
    private void successHandle(GroupBuyInfo s, List<GroupBuyUserRel> buyPersonNum, Random random, Integer groupRoleMainFlag) {
        s.setFinalResult((byte)1);
        groupBuyInfoMapper.updateByPrimaryKeySelective(s);
        //选择一个真实用户为中奖用户
        GroupBuyUserRel winFlagObj = null;
        if (groupRoleMainFlag.equals(2)) {
            List<GroupBuyUserRel> mainGroupRoleExclude = buyPersonNum.stream().filter(userRel -> userRel.getGroupRole() != (byte)1).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(mainGroupRoleExclude) && mainGroupRoleExclude.size() == 1) {
                winFlagObj = mainGroupRoleExclude.get(0);
            }else {
                winFlagObj = mainGroupRoleExclude.get(random.nextInt(mainGroupRoleExclude.size()));
            }
        }else {
            winFlagObj = buyPersonNum.get(random.nextInt(buyPersonNum.size()));
        }
        if (null == winFlagObj) {
            log.warn("===没有人中奖，原因：比如3人团，但是设置的时候只需要一人即可成团，但是规则中团主不能中奖，这时候就会出现这种情况==={}", s.getId());
            return;
        }
        winFlagObj.setWinFlag(1);
        groupBuyUserRelMapper.updateByPrimaryKeySelective(winFlagObj);

        try {
            doSendOrderRecordToKafka(winFlagObj.getOrderNo());
        } catch (Exception e) {
            log.error("===winFlagObj.getOrderNo()==={}", winFlagObj.getOrderNo());
            log.error("===发送拼团订单记录异常==={}", e);
        }
    }

    /**
     * 发送订单记录
     * @param orderNo
     */
    private void doSendOrderRecordToKafka(String orderNo) {
        Orders order = ordersService.selectOrderByNo(orderNo);
        if (null == order) {
            return;
        }
        List<OrdersInfo> ordersInfoList = ordersInfoMapper.selectOrderInfoByOrderId(order.getId());
        ordersInfoList.stream().forEach(orderInfo -> {
            Product product = productMapper.selectByPrimaryKey(orderInfo.getProductId());

            OrderRecordDto orderRecordDto = new OrderRecordDto(order.getUserId()==null?"0":String.valueOf(order.getUserId()),order.getId(), orderInfo.getId(), order.getOrderNo(), product.getId(), product.getProductName(),
                    product.getCostPrice(), product.getOriginalPrice(), product.getPrice(), order.getOrderSource(), order.getChannel(),
                    orderInfo.getActivityType(), IsPayConstant.NO.intValue(), org.apache.commons.lang3.StringUtils.isEmpty(order.getUserAddress()) ? 0 : 1, order.getCreateTime(), order.getIsFirstBuy(),
                    order.getUserId(),order.getPayType(),order.getPaySource(),order.getCity(),order.getArea(),order.getAddress(),order.getProvince(),
                    order.getUserAddress(),null,new Date(), order.getDynamicId());
            int count = yxOrdersSendRecordService.queryByOrderInfoId(orderInfo.getId(), 1);
            if(0 == count){
                OrdersSendRecord sendRecord = new OrdersSendRecord();
                sendRecord.setOrderinfoId(orderInfo.getId());
                sendRecord.setType((byte)1);
                sendRecord.setSucFlag((byte)1);
                sendRecord.setCreateTime(new Date());
                try {
                    rabbitTemplate.convertAndSend(QueueConstants.ORDER_RECORD_QUEUE,orderRecordDto);
                } catch (Exception e) {
                    log.error("===订单创建发送rabbitmq异常==={},{}", e, order);
                    sendRecord.setSucFlag((byte)0);
                }
                yxOrdersSendRecordService.insert(sendRecord);
            }

            orderRecordDto = new OrderRecordDto(order.getUserId()==null?"0":String.valueOf(order.getUserId()),order.getId(),orderInfo.getId(), order.getOrderNo(), product.getId(), product.getProductName(),
                    product.getCostPrice(), product.getOriginalPrice(), product.getPrice(), order.getOrderSource(), order.getChannel(),
                    orderInfo.getActivityType(), IsPayConstant.YES.intValue(), org.apache.commons.lang3.StringUtils.isEmpty(order.getUserAddress()) ? 0 : 1, order.getCreateTime(), order.getIsFirstBuy(),
                    order.getUserId(),order.getPayType(),order.getPaySource(),order.getCity(),order.getArea(),order.getAddress(),order.getProvince(),
                    order.getUserAddress(),order.getPayTime(),new Date(), order.getDynamicId());
            count = yxOrdersSendRecordService.queryByOrderInfoId(orderInfo.getId(), 2);
            if(0 == count){
                OrdersSendRecord sendRecord = new OrdersSendRecord();
                sendRecord.setOrderinfoId(orderInfo.getId());
                sendRecord.setType((byte)2);
                sendRecord.setSucFlag((byte)1);
                sendRecord.setCreateTime(new Date());
                try {
                    rabbitTemplate.convertAndSend(QueueConstants.ORDER_RECORD_QUEUE, orderRecordDto);
                } catch (Exception e) {
                    log.error("===订单支付发送rabbitmq异常==={},{}", e, order);
                    sendRecord.setSucFlag((byte)0);
                }
                yxOrdersSendRecordService.insert(sendRecord);
            }
        });
    }

    /**
     * 删除30分钟未支付的团成员信息
     * @return
     */
    public boolean deleteGrupBuyUserRel() {
        Date thirtyMinAfterDate = Date.from(LocalDateTime.now().plusMinutes(-3).atZone(ZoneId.systemDefault()).toInstant());//当前时间3分钟前的数据
        //已参团未支付的真实用户信息
        GroupBuyUserRelExample groupBuyUserRelExample = new GroupBuyUserRelExample();
        groupBuyUserRelExample.createCriteria().andCreateTimeLessThan(thirtyMinAfterDate).andStatusEqualTo(0).andVirtualUserEqualTo((byte)0);
        List<GroupBuyUserRel> buyPersonNum = groupBuyUserRelMapper.selectByExample(groupBuyUserRelExample);
        buyPersonNum.stream().forEach(s -> {
            int result = groupBuyUserRelMapper.deleteByPrimaryKey(s.getId());
            if (result > 0 && !StringUtils.isEmpty(s.getOrderNo())) {
                try {
                    log.info("===删除拼团超时未支付订单==={}", s.getOrderNo());
                    Integer orderId = ordersService.queryByOrderNo(s.getOrderNo());
                    ordersService.deleteByOrderNo(s.getOrderNo());
                    ordersInfoMapper.deleteByOrderId(orderId);
                } catch (Exception e) {
                    log.error("拼团定时任务删除订单异常:{},{}", s.getOrderNo(), e);
                }
            }
        });
        return true;
    }

    /**
     * 已成团未中奖的用户退款操作
     * @return
     */
    public boolean refundOrdersByGroupBuy() {
        //开团信息表
        GroupBuyInfoExample example = new GroupBuyInfoExample();
        example.createCriteria().andFinalResultEqualTo((byte)1);//.andEndTimeGreaterThan(new Date())
        List<GroupBuyInfo> groupInfos = groupBuyInfoMapper.selectByExample(example);
        groupInfos.stream().forEach(s -> {
            GroupBuyUserRelExample groupBuyUserRelExample = new GroupBuyUserRelExample();
            groupBuyUserRelExample.createCriteria().andStatusEqualTo(1)
                    .andVirtualUserEqualTo((byte)0)
                    .andWinFlagEqualTo(0)
                    .andRefundFlagEqualTo(0)
                    .andGroupIdEqualTo(s.getId())
                    .andOrderNoIsNotNull();
            List<GroupBuyUserRel> buyPersonNum = groupBuyUserRelMapper.selectByExample(groupBuyUserRelExample);
            buyPersonNum.stream().forEach(s2 -> {
                Integer orderId = ordersService.queryByOrderNo(s2.getOrderNo());
                String result = adminClient.refundOrdersByRpc(orderId, "拼团未中奖用户退款");
                log.info("===result==={}, {}", result, orderId);
                if ("200".equals(result)) {
                    s2.setRefundFlag(1);
                    groupBuyUserRelMapper.updateByPrimaryKeySelective(s2);
                }
            });
        });
        return true;
    }

    /**
     * 拼团失败用户退款
     * @return
     */
    public boolean refundOrdersByGroupBuyIsFail() {
        //开团信息表
        GroupBuyInfoExample example = new GroupBuyInfoExample();
        example.createCriteria().andFinalResultEqualTo((byte)2);//.andEndTimeGreaterThan(new Date())
        List<GroupBuyInfo> groupInfos = groupBuyInfoMapper.selectByExample(example);
        groupInfos.stream().forEach(s -> {
            GroupBuyUserRelExample groupBuyUserRelExample = new GroupBuyUserRelExample();
            groupBuyUserRelExample.createCriteria().andGroupIdEqualTo(s.getId()).andStatusEqualTo(1).andVirtualUserEqualTo((byte)0).andRefundFlagEqualTo(0).andOrderNoIsNotNull();
            List<GroupBuyUserRel> buyPersonNum = groupBuyUserRelMapper.selectByExample(groupBuyUserRelExample);
            buyPersonNum.stream().forEach(s2 -> {
                Integer orderId = ordersService.queryByOrderNo(s2.getOrderNo());
                String result = adminClient.refundOrdersByRpc(orderId, "拼团失败用户退款");
                log.info("===result==={}", result);
                if ("200".equals(result)) {
                    s2.setRefundFlag(1);
                    groupBuyUserRelMapper.updateByPrimaryKeySelective(s2);
                }
            });
        });
        return true;
    }

}
